
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

enum {
	PREFILTER_NORMALIZED_RESPONSE = 0,
	PREFILTER_XSOBEL = 1
};


struct BMParams
{
	BMParams(int _numDisparities = 64, int _SADWindowSize = 21)
	{
		preFilterType = PREFILTER_XSOBEL;
		preFilterSize = 9;
		preFilterCap = 31;
		SADWindowSize = _SADWindowSize;
		minDisparity = 0;
		numDisparities = _numDisparities > 0 ? _numDisparities : 64;
		textureThreshold = 10;
		uniquenessRatio = 15;
		speckleRange = speckleWindowSize = 0;
		roi1 = roi2 = Rect(0, 0, 0, 0);
		disp12MaxDiff = -1;
		dispType = CV_16S;
	}

	int preFilterType;
	int preFilterSize;
	int preFilterCap;
	int SADWindowSize;
	int minDisparity;
	int numDisparities;
	int textureThreshold;
	int uniquenessRatio;
	int speckleRange;
	int speckleWindowSize;
	Rect roi1, roi2;
	int disp12MaxDiff;
	int dispType;
};



class BM 
{
public:

	BM()
	{
		params = BMParams();
	}

	BM(int _numDisparities, int _SADWindowSize)
	{
		params = BMParams(_numDisparities, _SADWindowSize);
	}

	void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr);

	int getMinDisparity() const { return params.minDisparity; }
	void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; }

	int getNumDisparities() const { return params.numDisparities; }
	void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; }

	int getBlockSize() const { return params.SADWindowSize; }
	void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; }

	int getSpeckleWindowSize() const { return params.speckleWindowSize; }
	void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; }

	int getSpeckleRange() const { return params.speckleRange; }
	void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; }

	int getDisp12MaxDiff() const { return params.disp12MaxDiff; }
	void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; }

	int getPreFilterType() const { return params.preFilterType; }
	void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; }

	int getPreFilterSize() const { return params.preFilterSize; }
	void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; }

	int getPreFilterCap() const { return params.preFilterCap; }
	void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; }

	int getTextureThreshold() const { return params.textureThreshold; }
	void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; }

	int getUniquenessRatio() const { return params.uniquenessRatio; }
	void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; }

	int getSmallerBlockSize() const { return 0; }
	void setSmallerBlockSize(int) {}

	Rect getROI1() const { return params.roi1; }
	void setROI1(Rect roi1) { params.roi1 = roi1; }

	Rect getROI2() const { return params.roi2; }
	void setROI2(Rect roi2) { params.roi2 = roi2; }

	/*void write(FileStorage& fs) const
	{
		writeFormat(fs);
		fs << "name" << name_
			<< "minDisparity" << params.minDisparity
			<< "numDisparities" << params.numDisparities
			<< "blockSize" << params.SADWindowSize
			<< "speckleWindowSize" << params.speckleWindowSize
			<< "speckleRange" << params.speckleRange
			<< "disp12MaxDiff" << params.disp12MaxDiff
			<< "preFilterType" << params.preFilterType
			<< "preFilterSize" << params.preFilterSize
			<< "preFilterCap" << params.preFilterCap
			<< "textureThreshold" << params.textureThreshold
			<< "uniquenessRatio" << params.uniquenessRatio;
	}

	void read(const FileNode& fn)
	{
		FileNode n = fn["name"];
		CV_Assert(n.isString() && String(n) == name_);
		params.minDisparity = (int)fn["minDisparity"];
		params.numDisparities = (int)fn["numDisparities"];
		params.SADWindowSize = (int)fn["blockSize"];
		params.speckleWindowSize = (int)fn["speckleWindowSize"];
		params.speckleRange = (int)fn["speckleRange"];
		params.disp12MaxDiff = (int)fn["disp12MaxDiff"];
		params.preFilterType = (int)fn["preFilterType"];
		params.preFilterSize = (int)fn["preFilterSize"];
		params.preFilterCap = (int)fn["preFilterCap"];
		params.textureThreshold = (int)fn["textureThreshold"];
		params.uniquenessRatio = (int)fn["uniquenessRatio"];
		params.roi1 = params.roi2 = Rect();
	}*/

	BMParams params;
	Mat preFilteredImg0, preFilteredImg1, cost, dispbuf;
	Mat slidingSumBuf;

	//static const char* name_;
};

//const char* BM::name_ = "StereoMatcher.BM";
//Ptr<StereoBM> StereoBM::create(int _numDisparities, int _SADWindowSize)
//{
//	return makePtr<BM>(_numDisparities, _SADWindowSize);
//}


